﻿#ifndef _PKTBUF_H_
#define _PKTBUF_H_

#include <stdint.h>
#include <stdbool.h>
#include "nlist.h"
#include "debug.h"
#include "net_err.h"

// 采用链式方式存储数据包

// 数据块结构
typedef struct _pktblk_t
{
    nlist_node_t node;
    int size;
    uint8_t *data;                    // 存放数据的起始地址
    uint8_t payload[PKTBUF_BLK_SIZE]; // 存放数据
} pktblk_t;

// 数据包结构
typedef struct _pktbuf_t
{
    int total_size;     // 数据包的总大小
    nlist_t block_list; // 存放数据块的链表
    nlist_node_t node;  // 数据包之间也是以链表的形式存放

    int pos;
    uint8_t *blk_offset;
    pktblk_t *curr_blk;

    int ref; // 引用计数
} pktbuf_t;

static inline void pktbuf_increase_ref(pktbuf_t *buf)
{
    ++buf->ref;
}

net_err_t pktbuf_init();
pktbuf_t *pktbuf_alloc(u_int size);
uint8_t *pktbuf_data(pktbuf_t *buf);
net_err_t pktbuf_add_header(pktbuf_t *buf, int size, bool cont);
net_err_t pktbuf_remove_header(pktbuf_t *buf, int size);
net_err_t pktbuf_resize(pktbuf_t *buf, int to_size);
net_err_t pktbuf_join(pktbuf_t *dest, pktbuf_t *src);
net_err_t pktbuf_set_cont(pktbuf_t *buf, int size);
void pktbuf_free(pktbuf_t *buf);

// 数据包的访问读写相关
/**
 * @brief 数据包剩余可写的内存数量
 */
static inline int pktbuf_total_remain(pktbuf_t *buf)
{
    return buf->total_size - buf->pos;
}

/**
 * @brief 当前数据块剩余可写的数量
 */
static inline int pktbuf_blk_remain(pktbuf_t *buf)
{
    return (int)(buf->curr_blk->data + buf->curr_blk->size - buf->blk_offset);
}

net_err_t pktbuf_reset_acc(pktbuf_t *buf);
net_err_t pktbuf_write(pktbuf_t *buf, const uint8_t *src, int size);
net_err_t pktbuf_read(pktbuf_t *buf, uint8_t *dst, int buf_size, int dst_size);
net_err_t pktbuf_seek(pktbuf_t *buf, int offset);
net_err_t pktbuf_copy(pktbuf_t *dst, pktbuf_t *src, int size);
net_err_t pktbuf_fill(pktbuf_t *buf, uint8_t v, int size);

uint16_t pktbuf_checksum16(pktbuf_t *buf, int len, uint32_t pre_sum, bool complement);

#endif